﻿// MedicalRulesEngine.Core/Mappings/MappingProfile.cs
using AutoMapper;
using MedicalRulesEngine.Core.DTOs;
using MedicalRulesEngine.Domain.Entities;
using System.Text.Json;

namespace MedicalRulesEngine.Core.Mappings;

/// <summary>
/// AutoMapper映射配置
/// 定义实体与DTO之间的映射关系
/// </summary>
public class MappingProfile : Profile
{
    /// <summary>
    /// 构造函数
    /// </summary>
    public MappingProfile()
    {
        CreateRuleMappings();
        CreateFieldDefinitionMappings();
        CreateOperatorDefinitionMappings();
    }

    /// <summary>
    /// 创建规则相关映射
    /// </summary>
    private void CreateRuleMappings()
    {
        // MetadataRule -> RuleDto
        CreateMap<MetadataRule, RuleDto>()
            .ForMember(dest => dest.Status, opt => opt.MapFrom(src => (int)src.Status))
            .ForMember(dest => dest.Metadata, opt => opt.MapFrom(src =>
                string.IsNullOrWhiteSpace(src.MetadataJson) ? null : JsonSerializer.Deserialize<object>(src.MetadataJson, (JsonSerializerOptions?)null)))
            .ForMember(dest => dest.Conditions, opt => opt.MapFrom(src => src.Conditions))
            .ForMember(dest => dest.Actions, opt => opt.MapFrom(src => src.Actions))
            .ForMember(dest => dest.Tags, opt => opt.MapFrom(src => src.Tags));

        // RuleDto -> MetadataRule
        CreateMap<RuleDto, MetadataRule>()
            .ForMember(dest => dest.Status, opt => opt.MapFrom(src => (RuleStatus)src.Status))
            .ForMember(dest => dest.Priority, opt => opt.MapFrom(src => (RulePriority)src.Priority))
            .ForMember(dest => dest.MetadataJson, opt => opt.MapFrom(src =>
                src.Metadata != null ? JsonSerializer.Serialize(src.Metadata, (JsonSerializerOptions?)null) : null))
            .ForMember(dest => dest.Conditions, opt => opt.Ignore())
            .ForMember(dest => dest.Actions, opt => opt.Ignore())
            .ForMember(dest => dest.Tags, opt => opt.Ignore());

        // RuleCondition -> RuleConditionDto
        CreateMap<RuleCondition, RuleConditionDto>()
            .ForMember(dest => dest.Value, opt => opt.MapFrom(src =>
                string.IsNullOrWhiteSpace(src.Value) ? null : TryParseValue(src.Value)))
            .ForMember(dest => dest.Metadata, opt => opt.MapFrom(src =>
                string.IsNullOrWhiteSpace(src.MetadataJson) ? null : JsonSerializer.Deserialize<object>(src.MetadataJson, (JsonSerializerOptions?)null)))
            .ForMember(dest => dest.ChildConditions, opt => opt.MapFrom(src => src.ChildConditions));

        // RuleConditionDto -> RuleCondition
        CreateMap<RuleConditionDto, RuleCondition>()
            .ForMember(dest => dest.Value, opt => opt.MapFrom(src => src.Value != null ? src.Value.ToString() : null))
            .ForMember(dest => dest.MetadataJson, opt => opt.MapFrom(src =>
                src.Metadata != null ? JsonSerializer.Serialize(src.Metadata, (JsonSerializerOptions?)null) : null))
            .ForMember(dest => dest.ChildConditions, opt => opt.Ignore());

        // RuleAction -> RuleActionDto
        CreateMap<RuleAction, RuleActionDto>()
            .ForMember(dest => dest.Config, opt => opt.MapFrom(src =>
                string.IsNullOrWhiteSpace(src.ConfigJson) ? null : JsonSerializer.Deserialize<object>(src.ConfigJson, (JsonSerializerOptions?)null)));

        // RuleActionDto -> RuleAction
        CreateMap<RuleActionDto, RuleAction>()
            .ForMember(dest => dest.ConfigJson, opt => opt.MapFrom(src =>
                src.Config != null ? JsonSerializer.Serialize(src.Config, (JsonSerializerOptions?)null) : null));

        // RuleTag -> RuleTagDto
        CreateMap<RuleTag, RuleTagDto>();

        // RuleTagDto -> RuleTag
        CreateMap<RuleTagDto, RuleTag>();

        // CreateRuleRequest -> MetadataRule
        CreateMap<CreateRuleRequest, MetadataRule>()
            .ForMember(dest => dest.Id, opt => opt.MapFrom(src => Guid.NewGuid().ToString()))
            .ForMember(dest => dest.Priority, opt => opt.MapFrom(src => (RulePriority)src.Priority))
            .ForMember(dest => dest.Status, opt => opt.MapFrom(src => RuleStatus.Draft))
            .ForMember(dest => dest.IsEnabled, opt => opt.MapFrom(src => false))
            .ForMember(dest => dest.CreatedAt, opt => opt.MapFrom(src => DateTime.UtcNow))
            .ForMember(dest => dest.Version, opt => opt.MapFrom(src => 1))
            .ForMember(dest => dest.MetadataJson, opt => opt.MapFrom(src =>
                src.Metadata != null ? JsonSerializer.Serialize(src.Metadata, (JsonSerializerOptions?)null) : null))
            .ForMember(dest => dest.Conditions, opt => opt.Ignore())
            .ForMember(dest => dest.Actions, opt => opt.Ignore())
            .ForMember(dest => dest.Tags, opt => opt.Ignore());

        // CreateRuleConditionRequest -> RuleCondition
        CreateMap<CreateRuleConditionRequest, RuleCondition>()
            .ForMember(dest => dest.Id, opt => opt.MapFrom(src => Guid.NewGuid().ToString()))
            .ForMember(dest => dest.Value, opt => opt.MapFrom(src => src.Value != null ? src.Value.ToString() : null))
            .ForMember(dest => dest.MetadataJson, opt => opt.MapFrom(src =>
                src.Metadata != null ? JsonSerializer.Serialize(src.Metadata, (JsonSerializerOptions?)null) : null));

        // CreateRuleActionRequest -> RuleAction
        CreateMap<CreateRuleActionRequest, RuleAction>()
            .ForMember(dest => dest.Id, opt => opt.MapFrom(src => Guid.NewGuid().ToString()))
            .ForMember(dest => dest.ConfigJson, opt => opt.MapFrom(src =>
                src.Config != null ? JsonSerializer.Serialize(src.Config, (JsonSerializerOptions?)null) : null));

        // CreateRuleTagRequest -> RuleTag
        CreateMap<CreateRuleTagRequest, RuleTag>()
            .ForMember(dest => dest.Id, opt => opt.MapFrom(src => Guid.NewGuid().ToString()));
    }

    /// <summary>
    /// 创建字段定义映射
    /// </summary>
    private void CreateFieldDefinitionMappings()
    {
        // FieldDefinition -> FieldDefinitionDto
        CreateMap<FieldDefinition, FieldDefinitionDto>()
            .ForMember(dest => dest.Config, opt => opt.MapFrom(src =>
                string.IsNullOrWhiteSpace(src.ConfigJson) ? null : JsonSerializer.Deserialize<object>(src.ConfigJson, (JsonSerializerOptions?)null)))
            .ForMember(dest => dest.SupportedOperators, opt => opt.Ignore()); // 在服务层处理

        // FieldDefinitionDto -> FieldDefinition
        CreateMap<FieldDefinitionDto, FieldDefinition>()
            .ForMember(dest => dest.ConfigJson, opt => opt.MapFrom(src =>
                src.Config != null ? JsonSerializer.Serialize(src.Config, (JsonSerializerOptions?)null) : null))
            .ForMember(dest => dest.SupportedOperatorsJson, opt => opt.MapFrom(src =>
                src.SupportedOperators != null && src.SupportedOperators.Any() ? JsonSerializer.Serialize(src.SupportedOperators, (JsonSerializerOptions?)null) : null));
    }

    /// <summary>
    /// 创建操作符定义映射
    /// </summary>
    private void CreateOperatorDefinitionMappings()
    {
        // OperatorDefinition -> OperatorDefinitionDto
        CreateMap<OperatorDefinition, OperatorDefinitionDto>()
            .ForMember(dest => dest.SupportedDataTypes, opt => opt.Ignore()); // 在服务层处理

        // OperatorDefinitionDto -> OperatorDefinition
        CreateMap<OperatorDefinitionDto, OperatorDefinition>()
            .ForMember(dest => dest.SupportedDataTypesJson, opt => opt.MapFrom(src =>
                src.SupportedDataTypes != null && src.SupportedDataTypes.Any() ? JsonSerializer.Serialize(src.SupportedDataTypes, (JsonSerializerOptions?)null) : null));
    }

    /// <summary>
    /// 尝试解析值
    /// </summary>
    /// <param name="value">字符串值</param>
    /// <returns>解析后的对象</returns>
    private static object? TryParseValue(string value)
    {
        if (string.IsNullOrWhiteSpace(value))
            return null;

        // 尝试解析为数字
        if (double.TryParse(value, out var doubleValue))
            return doubleValue;

        // 尝试解析为布尔值
        if (bool.TryParse(value, out var boolValue))
            return boolValue;

        // 尝试解析为日期
        if (DateTime.TryParse(value, out var dateValue))
            return dateValue;

        // 尝试解析为JSON
        try
        {
            return JsonSerializer.Deserialize<object>(value, (JsonSerializerOptions?)null);
        }
        catch
        {
            // 解析失败，返回原始字符串
            return value;
        }
    }
}
